package models

import (
	"math"
	"strings"

	"learning.com/edu/utils/validator"
)

type PageFilter struct {
	Offset         int
	Page           int
	PageSize       int
	Sort          *string
	SortSafeList []string
}

func (f *PageFilter) ValidateFilters(v *validator.Validator) {
	v.Check(f.Offset >= 0, "offset", "must be greater than or equal to zero")
	v.Check(f.Page > 0, "page", "must be greater than zero")
	v.Check(f.Page < 10_000_000, "page", "must be less then a maximum of 10 million")
	v.Check(f.PageSize > 0, "page_size", "must be greater than zero")
	v.Check(f.PageSize <= 100, "page_size", "must be less then or equal a maximum of 100")
	if f.Sort != nil {
		v.Check(validator.PermittedValue(*f.Sort, f.SortSafeList...), "sort", "invalid sort value")
	}
}

func (f *PageFilter) sortColumn() *string {
	if f.Sort == nil {
		return nil
	}

	for _, safeValue := range f.SortSafeList {
		if *f.Sort == safeValue {
			ret := strings.TrimPrefix(*f.Sort, "-")
			return &ret
		}
	}

	// 不安全的排序参数
	panic("unsafe sort parameter:" + *f.Sort)
}

func (f *PageFilter) sortDirection() string {
	if f.Sort == nil {
		return "ASC"
	}
	if strings.HasPrefix(*f.Sort, "-") {
		return "DESC"
	} else {
		return "ASC"
	}
}

func (f *PageFilter) limit() int {
	return f.PageSize
}

func (f *PageFilter) start() int {
	return (f.Page - 1) * f.PageSize - f.Offset
}

type PageMeta struct {
	Offset       int `json:"offset"`
	CurrentPage  int `json:"current_page"`
	PageSize     int `json:"page_size"`
	FirstPage    int `json:"first_page"`
	LastPage     int `json:"last_page"`
	TotalRecords int `json:"total_records"`
}

func (f *PageFilter) calculateMetadata(totalRecords int) *PageMeta {
	return &PageMeta{
		Offset: f.Offset,
		CurrentPage: f.Page,
		PageSize: f.PageSize,
		FirstPage: 1,
		LastPage: int(math.Ceil(float64(totalRecords + f.Offset) / float64(f.PageSize))),
		TotalRecords: totalRecords,
	}
}